home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / xvectors / vector0.01.c next >
C/C++ Source or Header  |  1995-11-05  |  9KB  |  266 lines

  1. /****************************************************************************/
  2. /*                                        */
  3. /*                3D-Rotaion Routines                    */
  4. /*                                        */
  5. /*  CrEatOr: LarZ SamuelssoN                     AD: 1993         */
  6. /*                                        */
  7. /*  If everything works as planned these routines will be based on the      */
  8. /*  introduction of an Ortho-Normal-base in the vectorobject. The base,        */
  9. /*  consisting of three orthogonal vectors, will then be rotated and the    */
  10. /*  coordinates of the object's corners will be expressed as linear-        */
  11. /*  combinations of the three base-vectors.                     */
  12. /*  I will also try to substitute the sine-functions with sine-tables.      */
  13. /*  When calculating the perspective I will use logarithm- and             */
  14. /*  exponential-tables of the natural logarithm.                */
  15. /*  If I have any strenght left after these speed-ups I will look for        */
  16. /*  further optimizations.                             */
  17. /*                                        */
  18. /*  I will do my best to comment the code (I need 'em too)            */
  19. /*                                        */
  20. /****************************************************************************/
  21.  
  22. /****************************************************************************/
  23. /*                                        */
  24. /*  Version 0.01: Plain ordinary rotation... calculating every new point    */
  25. /*          by multiplying the rotation-matrix with the vector         */
  26. /*  (SLOW)      representing a corner in the object.                 */
  27. /*                                        */
  28. /****************************************************************************/
  29.  
  30. #include <X11/Xlib.h>    /* openscreen & drawing stuff                */
  31. #include <stdio.h>    /* the usual I/O                    */
  32. #include <math.h>    /* sin() and cos()                    */
  33. #include <stdlib.h>
  34.  
  35. #define    CORNERS 8    /* I will be rotating a cube which has 8 corners    */
  36. #define DIM    3    /* Nr of coordinates needed to descibe a corner     */
  37.  
  38. typedef    float     Vob[ CORNERS ][ DIM ];        /* my vector-object type    */
  39.  
  40. /* Draw a line relative (ox,oy) from (x,y) to (xe, ye) on rootwindow        */
  41. void DrawLine(int x, int y, int xe, int ye, int ox, int oy);
  42.  
  43. /* Initializes the X-Crap                            */
  44. void Init(void);
  45.  
  46. /* Makes X happy on exit                            */
  47. void Exit(void);
  48.  
  49. /* Clear the root (I bet you never could have guessed that)            */
  50. void Cls(void);
  51.  
  52. /* Calculates and returns the corners with perspective                */
  53. Vob * Perspect(Vob * em, int depth);
  54.  
  55. /* Calculates and 'returns' the corners rotated w1,w2,w3                   */
  56. void Rotate(Vob * em, float matrix[][ DIM ]);
  57.  
  58. /* Draws the object on the rootwindow with the corners are scaled         */
  59. void DrawOb(Vob * em, int scale, int cx, int cy, int pixel);
  60.  
  61. /* These are the variables set out to explore the unknown (X)                */
  62.  
  63. Display         *dpy;
  64. XColor             xcolour;
  65. GC             gc;
  66. XGCValues         xgcvalues;
  67. XSetWindowAttributes     xsetwattrs;
  68. int            scrn, pixel;
  69.  
  70. int main (void)
  71. {
  72.       int     cx = 600;    /* Center of rotation (rootwindow coords)   */
  73.     int     cy = 400;
  74.  
  75.     float     wx = 0;        /* Step-Rotation-Angles around the axises   */
  76.     float    wy = 0.02;
  77.     float    wz = 0;
  78.  
  79.     int     depth = 10;    /* Perspective depth                 */
  80.     int    scale = 200;    /* Scaling factor (in pixels)            */
  81.  
  82.     /* This is the object we will be dealing with, hence, a cube.        */
  83.     /* The numerous ones are the coordinates of the cube's corners and  */
  84.     /* three unos sealed in brackets represent a vector pointing at the */
  85.     /* corner of the cube. Everything is calculated relative the center */
  86.     /* of the cube, which is located in { 0, 0, 0 }                */
  87.  
  88.     Vob     cube =
  89.     {
  90.         {  1,  1,  1 },
  91.         {  1, -1,  1 },
  92.         {  1, -1, -1 },
  93.         {  1,  1, -1 },
  94.         { -1,  1, -1 },
  95.         { -1,  1,  1 },
  96.         { -1, -1,  1 },
  97.         { -1, -1, -1 },
  98.      };
  99.  
  100.     Vob *    pos;        /* Holds the position of the cube's corners */
  101.                 /* during the calculations            */
  102.  
  103.     float matrix[ DIM ][ DIM ];
  104.  
  105.     /* This is the rotation-matrix for rotation around three axises        */
  106.     /* and I won't explain the maths needed to understand it.         */
  107.     /* Further reading: (any?) University Text about Linear Algebra        */
  108.  
  109.     matrix[0][0] =  cos(wx) * cos(wy);
  110.       matrix[0][1] = -sin(wz) * cos(wx) - sin(wx) * sin(wy) * cos(wz);
  111.       matrix[0][2] =  sin(wx) * sin(wz) - sin(wy) * cos(wx) * cos(wz);
  112.       matrix[1][0] =  sin(wz) * cos(wy);
  113.       matrix[1][1] =     cos(wx) * cos(wz) - sin(wx) * sin(wy) * sin(wz);
  114.       matrix[1][2] = -sin(wx) * cos(wz) - sin(wy) * sin(wz) * cos(wx);
  115.       matrix[2][0] =  sin(wy);
  116.       matrix[2][1] =  sin(wx) * cos(wz);
  117.       matrix[2][2] =  cos(wx) * cos(wz);
  118.  
  119.     Init( );
  120.     Cls( );
  121.     pos = &cube;
  122.     while (4711)
  123.     {
  124.         DrawOb( Perspect( pos, depth ), scale, cx, cy, 
  125.             BlackPixel(dpy, scrn) );
  126.                             /* black */
  127.         Rotate( pos, matrix );
  128.  
  129.         DrawOb( Perspect( pos, depth ), scale, cx, cy, 
  130.             WhitePixel(dpy, scrn) );
  131.     }                        /* white */
  132.     Exit( );
  133.       return 0;
  134. }
  135.  
  136. void DrawOb(Vob * em, int scale, int cx, int cy, int pixel)
  137. {
  138.     Vob v;
  139.     int i;
  140.  
  141.     /* The mathematical cube (the one we use in our calcs)     */
  142.     /* has got a sidelenght of 1+1=2, which is quite small     */
  143.     /* if we consider it as pixels. Therefore we have to     */
  144.     /* scale the vectors by a number, i e scale determines  */
  145.     /* the on-screen-size of the cube            */    
  146.  
  147.     for ( i=0; i<CORNERS; i++ )
  148.     {
  149.         v[i][0] = scale*(*em)[i][0];
  150.         v[i][1] = scale*(*em)[i][1];
  151.     }
  152.                 /* set color */
  153.  
  154.     xgcvalues.foreground = pixel;
  155.       XChangeGC (dpy,gc,GCForeground, &xgcvalues);
  156.     
  157.     /* Cube specific - depends on how the cube was defined     */
  158.     /* in the array declaration. If you draw a picture of      */
  159.     /* the cube with it's center in oirgo (0,0,0) and plot     */
  160.     /* the corners ( {1,1,1}, {1,-1,1}, etc ) it's quite       */
  161.     /* easy to see which lines should be drawn.        */
  162.  
  163.     DrawLine(v[0][0], v[0][1], v[1][0], v[1][1], cx, cy);
  164.     DrawLine(v[1][0], v[1][1], v[2][0], v[2][1], cx, cy);
  165.     DrawLine(v[2][0], v[2][1], v[3][0], v[3][1], cx, cy);
  166.     DrawLine(v[3][0], v[3][1], v[4][0], v[4][1], cx, cy);
  167.     DrawLine(v[4][0], v[4][1], v[5][0], v[5][1], cx, cy);
  168.     DrawLine(v[5][0], v[5][1], v[6][0], v[6][1], cx, cy);
  169.     DrawLine(v[6][0], v[6][1], v[7][0], v[7][1], cx, cy);
  170.     DrawLine(v[6][0], v[6][1], v[1][0], v[1][1], cx, cy);
  171.     DrawLine(v[7][0], v[7][1], v[4][0], v[4][1], cx, cy);
  172.     DrawLine(v[5][0], v[5][1], v[0][0], v[0][1], cx, cy);
  173.     DrawLine(v[1][0], v[1][1], v[6][0], v[6][1], cx, cy);
  174.     DrawLine(v[3][0], v[3][1], v[0][0], v[0][1], cx, cy);
  175.     DrawLine(v[2][0], v[2][1], v[7][0], v[7][1], cx, cy);
  176. }
  177.  
  178. /* This is where the perspective is calculated. I use a method where I      */
  179. /* introduce a line on parametric form from a point on the z-axis to each   */
  180. /* of the cube's corners. I let the screen be the (x,y)-plane and project   */
  181. /* the corner point on to the screen ((x,y)-plane) in the direction of the  */
  182. /* line.                                    */
  183.  
  184. Vob * Perspect(Vob * em, int depth)
  185. {
  186.     Vob temp;
  187.     int i;    
  188.  
  189.     for ( i=0; i<CORNERS; i++ )
  190.     {
  191.         temp[i][0] = (*em)[i][0]*depth/(depth-(*em)[i][2]);
  192.         temp[i][1] = (*em)[i][1]*depth/(depth-(*em)[i][2]);
  193.     }
  194.     return &temp;
  195. }
  196.  
  197. /* This is where I multiply the matrix with the corner-vectors to yield     */
  198. /* the new corner-position. I use a temp vector to hold the values during   */
  199. /* claculation because I cannot change the 'real' values as they appear in  */
  200. /* every step of the calc.                            */
  201.  
  202. void Rotate(Vob * em, float matrix[][ DIM ])
  203. {
  204.         Vob temp;
  205.     int i,j;
  206.  
  207.     for ( i=0; i<CORNERS; i++ )            
  208.     {
  209.           temp[i][0] = matrix[0][0]*(*em)[i][0] +
  210.                      matrix[0][1]*(*em)[i][1] +
  211.                  matrix[0][2]*(*em)[i][2];
  212.           temp[i][1] = matrix[1][0]*(*em)[i][0] +
  213.                      matrix[1][1]*(*em)[i][1] +
  214.                  matrix[1][2]*(*em)[i][2];
  215.           temp[i][2] = matrix[2][0]*(*em)[i][0] +
  216.                      matrix[2][1]*(*em)[i][1] +
  217.                  matrix[2][2]*(*em)[i][2];
  218.     }
  219.     for ( i=0; i<CORNERS; i++ ) 
  220.         for ( j=0; j<DIM; j++ ) 
  221.             (*em)[i][j] = temp[i][j];
  222. }
  223.  
  224. /* Someone showed me how to initialize a screen and stuff in X so I can't   */
  225. /* explain any of the following stuff... The imprortance is that they work  */
  226. /* and the drawing routines are probably a bit different on the machines    */
  227. /* I'll be using these routines on later...                    */
  228.  
  229. void DrawLine(int x, int y, int xe, int ye, int ox, int oy)
  230. {
  231.     XDrawLine(dpy, RootWindow(dpy,scrn), gc, ox+x, oy+y, ox+xe, oy+ye);
  232. }
  233.  
  234. void Cls(void)
  235. {
  236.         XClearWindow(dpy,RootWindow(dpy,scrn));
  237. }
  238.  
  239. void Init(void)
  240. {
  241.     if (!(dpy = XOpenDisplay (NULL))) 
  242.        {
  243.               fprintf (stderr, "Cannot open display.\n");
  244.               exit(1);
  245.         }
  246.       scrn                 = DefaultScreen(dpy);
  247.     xsetwattrs.backing_store     = Always;
  248.      xsetwattrs.background_pixel     = BlackPixel(dpy,scrn);
  249.     pixel                 = WhitePixel(dpy,scrn);
  250.  
  251.       XChangeWindowAttributes(dpy,RootWindow(dpy,scrn),
  252.                  CWBackingStore|CWBackPixel,
  253.                 &xsetwattrs);
  254.       if (XParseColor(dpy, DefaultColormap(dpy,scrn), "khaki2", &xcolour))
  255.             if (XAllocColor (dpy, DefaultColormap(dpy,scrn), &xcolour))
  256.                   pixel = xcolour.pixel;
  257.  
  258.       gc = XCreateGC (dpy, RootWindow(dpy,scrn),0,NULL);
  259. }
  260.     
  261. void Exit(void)
  262. {
  263.     XFlush (dpy);
  264. }
  265.  
  266.